package jcu.sal.common.agents.netty;

import java.io.IOException;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;

import jcu.sal.common.Response;
import jcu.sal.common.agents.SALAgent;
import jcu.sal.common.cml.StreamCallback;
import jcu.sal.common.events.ClientEventHandler;
import jcu.sal.common.events.Event;

import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.channel.ChannelPipelineCoverage;
import org.jboss.netty.channel.ExceptionEvent;
import org.jboss.netty.channel.MessageEvent;
import org.jboss.netty.channel.SimpleChannelHandler;

/**
 * @author Marc Hammerton
 *
 */
@ChannelPipelineCoverage("one")
public class NettyClientHandler extends SimpleChannelHandler {

	public StreamCallback stream_cb = null;
	public ClientEventHandler eventHandler = null;
	public SALAgent agent = null;
	
	public long startTime = 0L;
	public int framesCounter = 0;
	
	public static final int maxFramesCounter = 1000;
	
	final BlockingQueue<Object> answer = new LinkedBlockingQueue<Object>();

	@Override
	public void messageReceived(ChannelHandlerContext chx, final MessageEvent e) {
		NettyMessage message = (NettyMessage) e.getMessage();
		switch(message.getType()) {
			case NettyConstants.RESP_SYNC_STRING:
			case NettyConstants.RESP_SYNC_STREAMID:
				answer.offer(message.getData(0));
				break;
			case NettyConstants.RESP_ASYNC_RESPONSE:
				framesCounter++;
				if (framesCounter == maxFramesCounter) {
					long timespan = System.nanoTime() - startTime;
					timespan = timespan / 1000000000; // change to seconds
					System.out.println("FPS: " + (framesCounter / timespan));
				}
				try {
					stream_cb.collect((Response) message.getData(0));
				} catch (IOException e1) {
					e1.printStackTrace();
				}
				break;
			case NettyConstants.RESP_ASYNC_EVENT:
				try {
					eventHandler.handle((Event) message.getData(0), agent);
				} catch (IOException e1) {
					e1.printStackTrace();
				}
				break;
			default:
				System.out.println(e.getMessage());
		}
	}
	
	@Override
	public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e)
			throws Exception {
		System.out.println("Client Exception:");
		System.out.println(e.getCause());
		e.getCause().printStackTrace();
	}


	public Object responseReceived() {
		for (;;) {
            try {
                return answer.take();
            } catch (InterruptedException e) {
                // Ignore.
            }
        }
	}
	
}
